/* 
 * File:   server.h
 * Author: zhouxich
 * Description: 包含相关头文件和服务器函数的声明还有相关结构的定义
 */
#ifndef SERVER_H
#define SERVER_H

#include <event2/event.h>
#include <event2/thread.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <event2/event-config.h>
#include <semaphore.h>
#include <queue>
#include <vector>
#include <map>
#include "csapp.h"
using namespace std;

#define NTHREAD 4
#define NWORKER 4
#define MAXNAME 256
#define MAXARGS 1024

typedef enum{
	GET, POST
}Method;

/*任务结构体*/
typedef struct{
	Method		req_method;
	bool		is_static;
	char		filename[MAXNAME];
	char		cgiargs[MAXARGS];
	int		    fd;
	int			content_length;
	evbuffer*	output;
	evbuffer*	input;
}task;

/*互斥量，信号量处理的任务队列，生产者消费者模型*/
typedef struct{
	queue<task>		task_queue;		// 任务队列，worker线程接收并处理
	pthread_mutex_t mutex;			// 保证对任务队列的互斥访问
	sem_t			not_full;		// 信号量，队列不满时，生产者可插入新任务
	sem_t			not_empty;		// 信号量，队列不空时，消费者可接收新任务
}task_handler;

/*全局变量，任务队列*/
extern task_handler handler;

/*全局变量，监听描述符*/
extern int sockfd;

/*各个epoll loop的event_base*/
extern event_base* base[NTHREAD];

int	tcp_listen(const char *, const char *, socklen_t *);
void on_read(struct bufferevent*, void*);
void eventcb(struct bufferevent*, short, void*);
void task_init(task_handler*, int);
void task_insert(task_handler*, task);
task task_get(task_handler*);
void*epoll_loop(void*);
void thread_make(int);
void*worker(void*);
void worker_make();

void read_requesthdrs(evbuffer*, int&);
bool parse_uri(Method, char *uri, char *filename, char *cgiargs);
void serve_static(evbuffer* output, int fd, char *filename, int filesize);
void get_filetype(char *filename, char *filetype);
void serve_dynamic(int fd, char *filename, char *cgiargs, 
			Method method, evbuffer* output, int);
void clienterror(evbuffer* output,int fd, char *cause, char *errnum, 
		 char *shortmsg, char *longmsg);
#endif
